import java.util.Arrays;
import java.util.ArrayList;

public class PrimeFactors {

  public static void main (String[] args) {

    int composite = Integer.parseInt(args[0]);
    PrimeChecker primeChecker = new PrimeChecker(composite);

    ArrayList<Integer> primeFactors = new ArrayList<Integer>();

    for (int i = 2; i <= composite; i++) {

      if (primeChecker.isPrime(i)) {

        while (composite % i == 0) {
          primeFactors.add(i);
          composite = composite / i;
        }

      }

    }

    for (Integer primeFactor : primeFactors) {
      System.out.print(primeFactor.toString() + ", ");
    }

  }

}

class PrimeChecker {

  private boolean[] primes;
  private boolean[] sieve;

  public PrimeChecker(int n) {
    findPrimesUpto(n);
  }

  public boolean isPrime(int n) {
    return primes[n];
  }

  private void findPrimesUpto(int n) {
    // Using the sieve of Eratosthenes
    // https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

    initializeSieveUpto(n);

    markCompositesInSieve();

    primes = sieve;

  }

  private void initializeSieveUpto(int n) {
    // initialize sieve with slots for numbers [2,n]
    // true at an index n means that n is prime
    // false means that it is a composite (non-prime)
    sieve = new boolean[n + 1];
    Arrays.fill(sieve, true);
    sieve[0] = sieve[1] = false; // 0 and 1 are not prime
  }

  private void markCompositesInSieve(){
    // starting with the first prime we know (2)..
    // ..traverse the whole sieve..
    for (int i = 2; i < sieve.length; i++) {
      // .. and whenever you find a prime..
      if (sieve[i]) {
        // mark all of its multiples as composites
        markAllMultiplesAsNonPrimes(i);
      }
    }
  }

  private void markAllMultiplesAsNonPrimes(int prime) {
    for (int times = 2; (prime * times) < sieve.length; times++) {
      sieve[prime * times] = false;
    }
  }

}
